Skip to content

fix: 요청 로그 매칭을 위해 requestId를 명시#621

Open
dh2906 wants to merge 1 commit intodevelopfrom
fix/620-request-log-correlation
Open

fix: 요청 로그 매칭을 위해 requestId를 명시#621
dh2906 wants to merge 1 commit intodevelopfrom
fix/620-request-log-correlation

Conversation

@dh2906
Copy link
Copy Markdown
Contributor

@dh2906 dh2906 commented Apr 29, 2026

🔍 개요


🚀 주요 변경 내용

  • runtime.error Slack 알림 본문에 MDC requestId를 명시합니다.
  • 요청 상세 DEBUG 로그의 Request, Headers, Query String, Body 라인에도 같은 requestId를 명시합니다.
  • 예상하지 못한 예외 경로에서 Slack 에러 알림과 DEBUG 요청 로그가 같은 requestId를 공유하는지 테스트로 고정합니다.

💬 참고 사항

  • 콘솔/파일 로그 패턴에는 이미 requestId가 포함되어 있었지만, runtime.error 로거는 별도 Slack appender를 사용하고 additivity=false라 Slack 알림 자체에는 식별자가 남지 않았습니다.
  • DEBUG 비활성화 시 요청 상세 로그를 계산하지 않는 기존 동작은 유지했습니다.
  • 검증: CI=true ./gradlew test --tests 'gg.agit.konect.unit.global.exception.GlobalExceptionHandlerTest' --rerun-tasks, CI=true ./gradlew checkstyleMain

✅ Checklist (완료 조건)

  • 코드 스타일 가이드 준수
  • 테스트 코드 포함됨
  • Reviewers / Assignees / Labels 지정 완료
  • 보안 및 민감 정보 검증 (API 키, 환경 변수, 개인정보 등)

- 런타임 에러 Slack 알림과 DEBUG 요청 로그가 같은 요청을 가리키는지 확정할 수 있도록 requestId를 함께 남긴다.

- runtime.error 로거가 별도 Slack appender만 사용해 콘솔/파일 로그 패턴의 MDC만으로는 매칭이 어려운 구조를 보완한다.

- DEBUG 요청 상세 로그에도 같은 requestId를 포함해 동시 요청 상황에서도 에러와 요청 본문을 구분할 수 있게 한다.
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 29, 2026

📝 Walkthrough

Walkthrough

GlobalExceptionHandler가 SLF4J MDC에서 requestId를 추출하여 Slack 에러 알림과 DEBUG 요청 로그에 포함시킵니다. 새로운 getRequestId() 헬퍼 메서드를 추가하여 MDC에서 requestId를 안전하게 읽고, 모든 디버그 로그에 요청 컨텍스트를 일관되게 적용합니다.

Changes

Cohort / File(s) Summary
Exception Handler Enhancement
src/main/java/gg/agit/konect/global/exception/GlobalExceptionHandler.java
MDC requestId 추출을 위한 getRequestId() 헬퍼 메서드 추가. 에러 Slack 메시지에 "Request ID" 라인 포함. DEBUG 요청 로그(메서드, URI, 헤더, 쿼리 문자열, 바디)에 requestId 프리픽스 추가.
Test Updates
src/test/java/gg/agit/konect/unit/global/exception/GlobalExceptionHandlerTest.java
각 테스트마다 MDC에 requestId 설정 및 정리. 예상 DEBUG 로그 출력에 "Request ID" 라인과 requestId 형식 포함 여부 검증 추가.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Possibly related PRs

Suggested labels

리팩토링

Poem

🐰 요청마다 추적 ID를 남기고,
디버그 로그에 실마리를 담아,
Slack 알림과 손을 맞잡으니,
에러도 더 이상 헷갈리지 않네요!
동시 요청 속에서도 누가 누군지,
한눈에 알 수 있는 마법이에요! ✨

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed PR 제목이 주요 변경사항인 requestId 명시를 정확히 반영하고 있으며, 변경사항의 핵심 목적을 명확히 전달합니다.
Description check ✅ Passed PR 설명이 변경사항의 개요, 주요 변경 내용, 참고 사항을 상세히 기술하고 있으며, 관련 이슈와 체크리스트를 포함합니다.
Linked Issues check ✅ Passed 코드 변경사항이 이슈 #620의 모든 목표를 충족합니다: Slack 알림에 MDC requestId 추가, DEBUG 로그에 requestId 포함, 테스트 추가로 매칭 검증.
Out of Scope Changes check ✅ Passed 모든 변경사항이 이슈 #620과 연관된 범위 내에 있으며, requestId 매칭 기능 구현과 테스트로만 구성되어 있습니다.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/620-request-log-correlation

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
Review rate limit: 0/1 reviews remaining, refill in 60 minutes.

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/main/java/gg/agit/konect/global/exception/GlobalExceptionHandler.java (1)

207-213: ⚠️ Potential issue | 🔴 Critical

[LEVEL: high] 예외 핸들러에서 스택트레이스 첫 요소를 무조건 참조하고 있습니다.
문제: Line 208의 e.getStackTrace()[0]는 스택트레이스가 비어있는 예외에서 ArrayIndexOutOfBoundsException을 유발할 수 있습니다.
영향: 런타임 예외 처리 중 2차 예외가 발생하면 Slack 알림과 표준 에러 응답 생성이 깨져 장애 분석이 어려워집니다.
제안: 스택트레이스 길이를 검사해 비어있을 때 안전한 기본 location 값을 사용하세요.

최소 수정 예시
-        StackTraceElement origin = e.getStackTrace()[0];
+        StackTraceElement[] stackTrace = e.getStackTrace();
+        StackTraceElement origin = stackTrace.length > 0 ? stackTrace[0] : null;
@@
-        String location = String.format("%s:%d", origin.getFileName(), origin.getLineNumber());
+        String location = origin == null
+            ? "unknown:0"
+            : String.format("%s:%d", origin.getFileName(), origin.getLineNumber());
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/main/java/gg/agit/konect/global/exception/GlobalExceptionHandler.java`
around lines 207 - 213, handleException currently does e.getStackTrace()[0]
(origin) which throws if the stack trace is empty; change handleException to
check e.getStackTrace() length (or null) before indexing and use a safe default
location string (e.g., "Unknown:0" or the exception class name) when empty, then
build uri, exception, location and message using that safe value so no secondary
ArrayIndexOutOfBoundsException occurs during error handling.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In
`@src/test/java/gg/agit/konect/unit/global/exception/GlobalExceptionHandlerTest.java`:
- Around line 105-106: The test in GlobalExceptionHandlerTest currently checks
.doesNotContain("Body: {\"name\":\"KONECT\"}") which misses the actual log
format that can leak sensitive data; update the assertion on the logger output
(the chain containing .doesNotContain(...)) to either replace or add a check for
.doesNotContain("Body [requestId:") so the test fails if the log contains the
"Body [requestId:"-style payload; locate the assertion in
GlobalExceptionHandlerTest and modify the doesNotContain call(s) accordingly.

---

Outside diff comments:
In `@src/main/java/gg/agit/konect/global/exception/GlobalExceptionHandler.java`:
- Around line 207-213: handleException currently does e.getStackTrace()[0]
(origin) which throws if the stack trace is empty; change handleException to
check e.getStackTrace() length (or null) before indexing and use a safe default
location string (e.g., "Unknown:0" or the exception class name) when empty, then
build uri, exception, location and message using that safe value so no secondary
ArrayIndexOutOfBoundsException occurs during error handling.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: e1778ff5-f10e-4c29-85ed-82c98be9199c

📥 Commits

Reviewing files that changed from the base of the PR and between c6b6dcc and 5e65295.

📒 Files selected for processing (2)
  • src/main/java/gg/agit/konect/global/exception/GlobalExceptionHandler.java
  • src/test/java/gg/agit/konect/unit/global/exception/GlobalExceptionHandlerTest.java
📜 Review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
  • GitHub Check: coverage
  • GitHub Check: Code Style Check
  • GitHub Check: Analyze (java-kotlin)
🧰 Additional context used
📓 Path-based instructions (4)
**/*.java

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

**/*.java: Java 코드에서 import로 해결할 수 있는 경우 FQCN(Full Qualified Class Name)을 사용하지 않도록 지적한다
JPA/QueryDSL 조회 변경 시 N+1, 잘못된 fetch join, count 쿼리 왜곡, pagination 깨짐, distinct 누락을 확인한다
권한 로직은 관리자 우회, 요청자와 대상자 관계, 클럽/채팅방/공지/일정의 소속 검증이 빠지지 않았는지 확인한다
soft delete, 탈퇴 사용자, 차단/제외 조건, 중복 제거가 필요한 조회에서는 응답에 노출되면 안 되는 데이터가 포함되는지 확인한다
DTO 응답 변경은 기존 클라이언트가 기대하는 필드명, nullability, enum/string 값, 정렬 순서를 깨지 않는지 확인한다
조건이 2개 이상 결합된 비즈니스 규칙, 권한 조건, soft delete 제외, 중복 제거, fallback 우선순위, 대표값 선택, DTO 변환, count 쿼리 분리, fetch join 선택 이유처럼 코드만으로 의도가 숨겨지는 지점에는 주석을 권장한다
단순 생성자 호출, 필드 매핑, 컬렉션 반환, 이름만으로 명확한 분기에는 주석을 요구하지 않는다

Files:

  • src/main/java/gg/agit/konect/global/exception/GlobalExceptionHandler.java
  • src/test/java/gg/agit/konect/unit/global/exception/GlobalExceptionHandlerTest.java
**/*.{sql,java}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

데이터베이스 변경에서는 마이그레이션 순서, 기존 데이터 호환성, nullable/default 처리, 롤백 난이도, 인덱스 필요성을 확인한다

Files:

  • src/main/java/gg/agit/konect/global/exception/GlobalExceptionHandler.java
  • src/test/java/gg/agit/konect/unit/global/exception/GlobalExceptionHandlerTest.java
src/main/java/**/*.java

⚙️ CodeRabbit configuration file

src/main/java/**/*.java: 아래 원칙으로 리뷰 코멘트를 작성한다.

  • 코멘트는 반드시 한국어로 작성한다.
  • 반드시 수정이 필요한 항목만 코멘트로 남기고, 단순 취향 차이는 지적하지 않는다.
  • 각 코멘트 첫 줄에 심각도를 [LEVEL: high|medium|low] 형식으로 반드시 표기한다.
  • 심각도 기준: high=운영 장애 가능, medium=품질 저하, low=개선 권고.
  • 각 코멘트는 "문제 -> 영향 -> 제안" 순서로 3문장 이내로 간결하게 작성한다.
  • 가능하면 재현 조건 및 실패 시나리오도 포함한다.
  • 제안은 현재 코드베이스(Spring Boot + JPA + Flyway) 패턴과 일치해야 한다.
  • 보안, 트랜잭션 경계, 예외 처리, N+1, 성능 회귀 가능성을 우선 점검한다.
  • 가독성: 변수/메서드 이름이 의도를 바로 드러내는지, 중첩과 메서드 길이가 과도하지 않은지 점검한다.
  • 단순화: 불필요한 추상화, 중복 로직, 과한 방어 코드가 있으면 더 단순한 대안을 제시한다.
  • 확장성: 새 요구사항 추가 시 변경 범위가 최소화되는 구조인지(하드코딩 분기/값 여부 포함) 점검한다.

Files:

  • src/main/java/gg/agit/konect/global/exception/GlobalExceptionHandler.java
**/*

⚙️ CodeRabbit configuration file

**/*: 공통 리뷰 톤 가이드:

  • 모든 코멘트는 첫 줄에 [LEVEL: ...] 태그를 포함한다.
  • 과장된 표현 없이 사실 기반으로 작성한다.
  • 한 코멘트에는 하나의 이슈만 다룬다.
  • 코드 예시가 필요하면 최소 수정 예시를 제시한다.
  • 가독성/단순화/확장성 이슈를 발견하면 우선순위를 높여 코멘트한다.

Files:

  • src/main/java/gg/agit/konect/global/exception/GlobalExceptionHandler.java
  • src/test/java/gg/agit/konect/unit/global/exception/GlobalExceptionHandlerTest.java
🧠 Learnings (1)
📚 Learning: 2026-04-25T06:58:54.405Z
Learnt from: CR
Repo: BCSDLab/KONECT_BACK_END PR: 0
File: src/main/java/gg/agit/konect/domain/notification/AGENTS.md:0-0
Timestamp: 2026-04-25T06:58:54.405Z
Learning: Applies to src/main/java/gg/agit/konect/domain/notification/**/*IntegrationTest*.java : Add regression tests for: club application event rollback resulting in zero notifications created (AFTER_COMMIT integration test), inbox list/unread count/bulk read excluding chat-related types (repository integration test), Expo push partial ticket failures logged without whole-request exception propagation, group chat token vs target user count mismatch in current policy.

Applied to files:

  • src/test/java/gg/agit/konect/unit/global/exception/GlobalExceptionHandlerTest.java

Comment on lines +105 to 106
.doesNotContain("Request [requestId:")
.doesNotContain("Body: {\"name\":\"KONECT\"}");
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

[LEVEL: low] DEBUG 비활성화 테스트의 Body 검증 문자열이 현재 포맷과 불일치합니다.
문제: Line 106이 Body: {"name":"KONECT"} 구포맷만 검사해서 Body [requestId: ...] 형태의 본문 로그 누출을 직접 검출하지 못합니다.
영향: DEBUG OFF 회귀가 발생해도 테스트가 통과해 민감 정보 로깅 회귀를 놓칠 수 있습니다.
제안: 현재 포맷 기준으로 doesNotContain("Body [requestId:") 검증을 추가하거나 교체하세요.

최소 수정 예시
         assertThat(output)
             .doesNotContain("Request [requestId:")
-            .doesNotContain("Body: {\"name\":\"KONECT\"}");
+            .doesNotContain("Body [requestId:");
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@src/test/java/gg/agit/konect/unit/global/exception/GlobalExceptionHandlerTest.java`
around lines 105 - 106, The test in GlobalExceptionHandlerTest currently checks
.doesNotContain("Body: {\"name\":\"KONECT\"}") which misses the actual log
format that can leak sensitive data; update the assertion on the logger output
(the chain containing .doesNotContain(...)) to either replace or add a check for
.doesNotContain("Body [requestId:") so the test fails if the log contains the
"Body [requestId:"-style payload; locate the assertion in
GlobalExceptionHandlerTest and modify the doesNotContain call(s) accordingly.

@github-actions
Copy link
Copy Markdown

🧪 JaCoCo Coverage Report (Changed Files)

변경된 main Java 소스 파일에 대한 JaCoCo 데이터가 없습니다.

📊 View Workflow Run

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

fix: 에러 알림과 요청 디버그 로그 requestId 매칭

1 participant